#include <iostream>
#include <cstring>
#include <cassert>
#include <cstdlib>
#include <time.h>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// 设定进程个数
#define PROCNUM 3
// 设定种子随机分配任务给任意子进程
#define RandSet() srand((unsigned long)time(nullptr) ^ getpid() ^ 0x171237 ^ rand() % 1234)
// 函数指针 类型
typedef void (*func)();

class proc
{
public:
    proc(pid_t wfd, int child_pid)
        : _wfd(wfd),
          _child_pid(child_pid) {}

    pid_t _wfd;
    int _child_pid;

private:
};

//////////////////任务栏////////////////////////
void FFlush_Task()
{
    printf("FFlush--Success\n");
}

void Output_Task()
{
    printf("OutPut--Success\n");
}

void Input_Task()
{
    printf("InPut--Success\n");
}
////////////////////////////////////////////////
/// 加载任务栏
void Load_Task(std::vector<func> &TaskSList)
{
    TaskSList.push_back(FFlush_Task);
    TaskSList.push_back(Input_Task);
    TaskSList.push_back(Output_Task);
    if (TaskSList.size() == 3)
        printf("Task Load Success\n");
    else
        printf("Task Load Failure\n");
}
/// 子进程执行任务
void Operator_Task(std::vector<func> &TaskSList, int fd)
{
    while (true)
    {
        int option;
        // 获取任务,若没有任务应堵塞
        int rev = read(fd, &option, sizeof(int));
        // 管道写端关闭,子进程读完文件直至0为止
        if (rev == 0)
        {
            close(fd);
            exit(0);
        }
        std::cout << "我是子进程:" << getpid() << " 我在执行任务: ";
        TaskSList[option]();
    }
}
/// 创建子进程
void Creat_ChildForks(std::vector<proc> &subs, std::vector<func> &TaskSList)
{
    for (size_t i = 0; i < PROCNUM; ++i)
    {
        int fd[2];
        // 建立匿名管道
        int ret = pipe(fd);
        assert(ret == 0);
        (void)ret;
        // 子进程创建
        pid_t child_pid = fork();
        if (child_pid == -1)
        {
            std::cout << "errno:" << errno << " " << strerror(errno) << std::endl;
            exit(1);
        }
        else if (child_pid == 0)
        {
            close(fd[1]);
            Operator_Task(TaskSList, fd[0]);
        }
        close(fd[0]);
        proc child_proc(fd[1], child_pid);
        subs.push_back(child_proc);
    }
}

void Control_ChildFork(std::vector<proc> &subs, std::vector<func> &TaskSList, int &cnt)
{
    bool Forever = (cnt == 0) ? true : false;
    while (cnt)
    {
        // 选择任务
        int task_index = rand() % TaskSList.size();
        // 选择子进程
        int proc_index = rand() % subs.size();
        // 发送任务
        if (!Forever)
            cnt--;
        write(subs[proc_index]._wfd, &task_index, sizeof(int));
        sleep(1);
    }
}

void ClosePipe(std::vector<proc> &subs)
{
    for (size_t i = 0; i < PROCNUM; ++i)
        close(subs[i]._wfd);
}

void WaitProcess(std::vector<proc> &subs)
{
    for (size_t i = 0; i < PROCNUM; ++i)
        waitpid(subs[i]._child_pid, nullptr, 0);
    std::cout << "所有进程回收完毕" << std::endl;
}

int main()
{
    RandSet();
    std::vector<func> TaskSList;
    std::vector<proc> subs;
    Load_Task(TaskSList);
    Creat_ChildForks(subs, TaskSList);
    // 父进程控制子进程模块
    int cnt = 10;
    Control_ChildFork(subs, TaskSList, cnt);
    // 关闭管道
    ClosePipe(subs);
    // 回收子进程资源
    WaitProcess(subs);
    return 0;
}
